home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / 3D Class Library / main.cp < prev    next >
Text File  |  1996-06-27  |  9KB  |  383 lines

  1. // =======================================================================
  2. //    3D Class Library, © Xilex Group
  3. // - ------------------------------------------------------------------- -
  4. //    Written by Dmitry Boldyrev
  5. // =======================================================================
  6.  
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include <QDOffscreen.h>
  10. #include <profiler.h>
  11. #include "3dcl.h"
  12.  
  13. Point    middle;
  14.  
  15. Ptr baseAddr;
  16. short rowBytes;
  17.  
  18. UBYTE *thepic;
  19.  
  20. typedef struct
  21. {
  22.     unsigned char    r:8, g:8, b:8;
  23. } color;
  24.  
  25. color *pal;
  26.  
  27. Rect        rBounds;
  28.  
  29. #define    iHandCursor                200
  30. #define    iNewHandCursor            201
  31.  
  32. static void InitToolBox()
  33. {
  34.     EventRecord    event;
  35.     short        count;
  36.     
  37.     InitGraf((Ptr) &qd.thePort);
  38.     InitFonts();
  39.     InitWindows();
  40.     InitMenus();
  41.     TEInit();
  42.     InitDialogs(0L);
  43.     InitCursor();
  44.     SetEventMask(everyEvent);
  45.  
  46.     for (count = 1; count <= 3; count++) {
  47.         MoreMasters();
  48.         EventAvail(everyEvent, &event);
  49.     }
  50.     FlushEvents(everyEvent, 0);
  51. }
  52.  
  53. static void load_pic (void)
  54. {
  55.     FILE *fp;
  56.     
  57.     thepic = new UBYTE[65535];
  58.     pal = new color[256];
  59.     
  60.     fp = fopen ("o021.raw", "rb");
  61.     fread (pal, 1, sizeof(color) * 256, fp);           /* Load the palette */
  62.     fread (thepic, 1, 65535, fp);                      /* Load the picture */
  63.     fclose (fp);
  64. }
  65.  
  66. static void delete_pic (void)
  67. {
  68.     delete[] pal;
  69.     delete[] thepic;
  70. }
  71.  
  72. #define    kDiffuse        24
  73. #define    kSpecular        (32 - kDiffuse)
  74.  
  75. #define    MAXCOL    64
  76.  
  77. static unsigned char closest_match (int red, int green, int blue, color *pal)
  78. {
  79. int colnum;                     /* Color number to compare */
  80. int delta_r, delta_g, delta_b;  /* Difference between new and existing */
  81. float distance;                 /* Distance from new color */
  82. float lowest_distance;          /* Lowest distance found */
  83. int closest_color;              /* Color with the lowest distance */
  84.  
  85.  
  86.    lowest_distance = 33333;
  87.    /* Set to a high number, higher than anything possible.
  88.       The highest distance we can have is sqrt (64*64 + 64*64 + 64*64)
  89.       which is 110.85 */
  90.  
  91.    for  (colnum = 0; colnum < MAXCOL; colnum++)
  92.    /* Compare each color from the existing palette */
  93.      {
  94.  
  95.       delta_r = (pal[colnum].r - red);
  96.       delta_g = (pal[colnum].g - green);
  97.       delta_b = (pal[colnum].b - blue);
  98.  
  99.       distance = sqrt (delta_r*delta_r*30 + delta_g*delta_g*59 + delta_b*delta_b*11);
  100.  
  101.       if  (distance < lowest_distance)
  102.         {
  103.          lowest_distance = distance;
  104.          closest_color = colnum;
  105.         }
  106.      }
  107.  
  108.  return (closest_color);
  109. }
  110.  
  111.  
  112. static void create_fade_table (int frame, int maxframe,
  113.                         unsigned char *fadetable, color *pal)
  114. {
  115.  
  116. float lightlevel1;      /* Percentage of color 1 */
  117. float lightlevel2;      /* Percentage of color 2 */
  118.  
  119. float fr, fg, fb;       /* Floating point RGB values of color 1 */
  120. float fr2, fg2, fb2;    /* Floating point RGB values of color 2 */
  121. int   ir,  ig,  ib;     /* Integer RGB values after combing the two above */
  122.  
  123. int col1, col2;
  124.  
  125. unsigned char bestcolor; /* Best match */
  126.  
  127.  lightlevel1 = (float)frame / (float)maxframe;
  128.  /* Calculate the percentage of color 1 */
  129.  
  130.  lightlevel2 = 1.0 - lightlevel1;
  131.  /* Percentage of color 2 is the 100% - lightlevel1 */
  132.  
  133.  
  134.  for (col2 = 0; col2 < MAXCOL; col2++)
  135.    for (col1 = 0; col1 < MAXCOL; col1++)
  136.      {
  137.       
  138.       fr = (float)pal[col1].r * lightlevel1;
  139.       fg = (float)pal[col1].g * lightlevel1;
  140.       fb = (float)pal[col1].b * lightlevel1;
  141.  
  142.       fr2= (float)pal[col2].r * lightlevel2;
  143.       fg2= (float)pal[col2].g * lightlevel2;
  144.       fb2= (float)pal[col2].b * lightlevel2;
  145.  
  146.       /* Calculate the two new colors */
  147.  
  148.       ir = (fr + fr2);
  149.       ig = (fg + fg2);
  150.       ib = (fb + fb2);
  151.       /* Combine the percentage of color 1 with the percentage of color 2
  152.          to form a new color */
  153.  
  154.       bestcolor = closest_match (ir, ig, ib, pal);
  155.  
  156.       fadetable[frame * (MAXCOL*MAXCOL) + col2 * MAXCOL + col1] = bestcolor;
  157.    }
  158.  
  159. }
  160.  
  161. #define    NUMFRAMES    10
  162.  
  163. static void InitPalette(CTabHandle ctab)
  164. {
  165.     WORD        ptr, i;
  166.     RGBColor    color;
  167.     UBYTE        *fadetable;
  168.     
  169.     fadetable = new UBYTE[MAXCOL * MAXCOL * (NUMFRAMES / 2)];
  170.     
  171.     for (i = 0; i < NUMFRAMES/2; i++)
  172.     { 
  173.         create_fade_table (i, NUMFRAMES, fadetable, pal);
  174.     }
  175.     
  176.     for(i=0; i<256; i++) 
  177.     {
  178.         color.red     = pal[i].r * 256L;
  179.         color.green = pal[i].g * 256L;
  180.         color.blue     = pal[i].b * 256L;
  181.                         
  182.         (*ctab)->ctTable[i].rgb = color;
  183.     }
  184.     SetEntries(0,  255, (*ctab)->ctTable);
  185. }
  186.  
  187. #define kAmbient    0.3
  188.  
  189. static void MakePalette(CTabHandle ctab)
  190. {
  191.     short        i, j, specular, diffuse, pal_index;
  192.     RGBColor    col, color, background;
  193.     
  194.     color.red     = 65535;
  195.     color.green = 0;
  196.     color.blue     = 0;
  197.  
  198.     col.red     = color.red * kAmbient;
  199.     col.green     = color.green * kAmbient;
  200.     col.blue     = color.blue * kAmbient;
  201.     
  202.     
  203.     pal_index = 0;
  204.     for(j=0; j<kDiffuse; j++) 
  205.     {
  206.         col.red += (color.red - col.red) / (kDiffuse-j);
  207.         col.green += (color.green - col.green) / (kDiffuse-j);
  208.         col.blue += (color.blue - col.blue) / (kDiffuse-j);
  209.                         
  210.         (*ctab)->ctTable[pal_index++].rgb = col;
  211.     }
  212.  
  213.     color.red = 0xFFFF;
  214.     color.green = 0xFFFF;
  215.     color.blue = 0xFFFF;
  216.     for(j=0; j<kSpecular; j++) 
  217.     {
  218.         col.red += (color.red - col.red) / (kSpecular-j);
  219.         col.green += (color.green - col.green) / (kSpecular-j);
  220.         col.blue += (color.blue - col.blue) / (kSpecular-j);
  221.         
  222.         (*ctab)->ctTable[pal_index++].rgb = col;
  223.     }
  224.     SetEntries(0,  254, (*ctab)->ctTable);
  225. }
  226.  
  227. void main(void)
  228. {
  229.     char    str[255];
  230.     LONG    TickStart, FrameCount;
  231.     
  232.     InitToolBox();
  233.     load_pic();
  234.     
  235.     object3d    object;
  236.     
  237.     object.importV3D("text.v3d");
  238.  
  239.      WindowPtr     window;
  240.     GWorldPtr    gWorld;
  241.     OSErr        iErr;
  242.     CGrafPtr    savePort;
  243.     GDHandle    saveGDev;
  244.     PixMapHandle    pixBase;
  245.     GDHandle    iMainScreen;
  246.     PixMapPtr    iPixMap;
  247.     
  248.     window = ::GetNewCWindow(128, NULL, (WindowPtr) -1);
  249.     ::ShowWindow(window);
  250.     ::SetPort(window);    
  251.     
  252.     iMainScreen = GetMainDevice();
  253.     iPixMap = *((**iMainScreen).gdPMap);
  254.     MakePalette(iPixMap->pmTable);
  255.                 
  256.     rBounds = window->portRect;
  257.     ::OffsetRect(&rBounds, -rBounds.left, -rBounds.top);
  258.     ::SetPt(&middle, rBounds.right >> 1, rBounds.bottom >> 1);
  259.     
  260.     iErr = ::NewGWorld(&gWorld, 8, &rBounds, iPixMap->pmTable, NULL, keepLocal);
  261.     if (iErr != noErr)
  262.     {
  263.         ::DisposeWindow(window);
  264.         return;
  265.     }
  266.     pixBase = ::GetGWorldPixMap(gWorld);
  267.     ::LockPixels(pixBase);
  268.     ::HLockHi((Handle) pixBase);
  269.     
  270.     baseAddr = (**pixBase).baseAddr;
  271.     rowBytes = (**pixBase).rowBytes & 0x1FFF;
  272.     
  273.     ::BackColor( whiteColor );
  274.     ::ForeColor( blackColor );
  275.     
  276.     ::GetGWorld(&savePort, &saveGDev);
  277.      ::SetGWorld(gWorld, NULL);
  278.      ::BackColor(blackColor);
  279.      ::ForeColor(whiteColor);
  280.      ::SetGWorld(savePort, saveGDev);
  281.  
  282.     EventRecord event;
  283.     BOOL quit = FALSE;
  284.                         
  285. #ifdef use_profiler
  286.    if (::ProfilerInit(collectDetailed, bestTimeBase, 100, 10) != noErr)
  287.       ::ExitToShell();          
  288. #endif
  289.     TickStart = ::TickCount();
  290.     FrameCount = 0;
  291.     
  292.     
  293.     object.applyTexture();
  294.     object.makeRotMatrix(0, 0, 0);
  295.     object.setGNormals();        
  296.     object.localRotate();
  297.  
  298.     Point curPt, oldPt;
  299.     LONG  diffPt;
  300.     BOOL  down;
  301.     
  302.     ::GetMouse(&curPt);
  303.       oldPt = curPt;
  304.     while (!quit)
  305.     {
  306.         GetMouse(&curPt);
  307.         if (PtInRect(curPt, &window->portRect)) {
  308.             if (::StillDown())
  309.             {
  310.                 ::SetCursor(*GetCursor(iNewHandCursor));
  311.                 down = TRUE;
  312.             } else
  313.             {
  314.                 ::SetCursor(*GetCursor(iHandCursor));
  315.                 down = FALSE;
  316.             }
  317.         } else
  318.             ::SetCursor(&qd.arrow);
  319.  
  320.         ::SetGWorld(gWorld, NULL);
  321.         ::EraseRect(&rBounds);
  322.         if (!::EqualPt(curPt, oldPt) && down)
  323.         {    
  324.  
  325.             if (event.modifiers & optionKey)
  326.             {
  327.                 camera.view.z += (curPt.v - oldPt.v) * 100;
  328.                 object.localRotate();
  329.             } else
  330.             {
  331.                 object.makeRotMatrix(down ? curPt.v - oldPt.v : 0, 
  332.                           down ? curPt.h - oldPt.h : 0, 0);
  333.                 object.setGNormals();        
  334.                 object.localRotate();
  335.             }
  336.         
  337.             oldPt = curPt;
  338.             
  339.         }
  340.         object.display();        
  341.  
  342.         ::sprintf(str, "fps: %.2f", (FrameCount * 60.0) / (::TickCount() - TickStart));
  343.         ::MoveTo(10, 20);
  344.         ::DrawText(str, 0, strlen(str));
  345.         
  346.         ::SetGWorld(savePort, saveGDev);
  347.     
  348.         ::CopyBits(*(BitMap**) gWorld->portPixMap, *(BitMap**) savePort->portPixMap,
  349.                     &rBounds, &rBounds, srcCopy, NULL);
  350.         if (::WaitNextEvent(everyEvent, &event, 0, NULL)) 
  351.         {
  352.             if (event.what == mouseDown)
  353.             {
  354.                 WindowPtr     theWindow;
  355.                 short        iWinPart;
  356.                 
  357.                 iWinPart = ::FindWindow(event.where, &theWindow);
  358.                 switch (iWinPart)
  359.                 {
  360.                     case inGoAway:
  361.                         if (::TrackGoAway(theWindow, event.where)) 
  362.                             quit = TRUE;
  363.                         break;
  364.                     case inContent:
  365.                         oldPt = curPt;
  366.                         break;
  367.                 }
  368.             }
  369.         }
  370.         FrameCount++;
  371.     }
  372. #ifdef use_profiler
  373.     ::ProfilerDump("\pProfilerIntro.profiler");
  374.     ::ProfilerTerm();
  375. #endif
  376.     ::FlushEvents(everyEvent, 0);
  377.     
  378.     delete_pic();
  379.     ::DisposeGWorld(gWorld);
  380.     ::DisposeWindow(window);
  381. }
  382.  
  383.